/*
 * Copyright (C) 2009 Show SMS open source project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.bydavy.android.showsms.ui;

//~--- non-JDK imports --------------------------------------------------------

import android.content.Context;

import android.util.AttributeSet;

import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;

import android.widget.ViewAnimator;

import com.bydavy.android.showsms.R;
import com.bydavy.android.showsms.model.Conversation;
import com.bydavy.android.showsms.model.Conversation.UpdateMessagesListener;
import com.bydavy.android.showsms.model.ShortMessage;
import com.bydavy.android.showsms.util.AppLog;

//~--- JDK imports ------------------------------------------------------------

import java.util.HashSet;
import java.util.Set;

//~--- classes ----------------------------------------------------------------

public class ConversationCenterView extends ViewAnimator implements UpdateMessagesListener {
    //~--- static fields ------------------------------------------------------

    private static final String LOG_TAG = AppLog.LOG_TAG;
    private static final boolean DEBUG  = true;
    protected static int MAJOR_MOVE     = 120;

    //~--- fields -------------------------------------------------------------

    private Conversation mConversation;
    private Animation mAnimLeftIn;
    private Animation mAnimLeftOur;
    private Animation mAnimRightIn;
    private Animation mAnimRightOut;
    private GestureDetector mGestureDetector;
    private Set<ConversationViewListener> mListeners = new HashSet<ConversationViewListener>();
    private int mMessageVisibleIndex;
    private Thread mUiThread;

    //~--- constructors -------------------------------------------------------

    public ConversationCenterView(Context context) {
        super(context);
        mUiThread = Thread.currentThread();
    }

    public ConversationCenterView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mUiThread = Thread.currentThread();
    }

    //~--- get methods --------------------------------------------------------

    public boolean hasPreviousMessage() {
        if ((mMessageVisibleIndex + 1) < mConversation.getMessageCount()) {
            return true;
        }

        return false;
    }

    public boolean hasNextMessage() {
        if (mMessageVisibleIndex > 0) {
            return true;
        }

        return false;
    }

    private ShortMessageView getRecycledView() {
        if (getDisplayedChild() == 0) {
            return (ShortMessageView) getChildAt(1);
        } else {
            return (ShortMessageView) getChildAt(0);
        }
    }

    //~--- methods ------------------------------------------------------------

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

        mAnimLeftIn   = AnimationUtils.loadAnimation(getContext(), R.anim.slide_left_in);
        mAnimLeftOur  = AnimationUtils.loadAnimation(getContext(), R.anim.slide_left_out);
        mAnimRightIn  = AnimationUtils.loadAnimation(getContext(), R.anim.slide_right_in);
        mAnimRightOut = AnimationUtils.loadAnimation(getContext(), R.anim.slide_right_out);

        setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                mGestureDetector.onTouchEvent(event);

                return true;
            }
        });

        mGestureDetector = new GestureDetector(new GestureDetector.SimpleOnGestureListener() {
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                int dx = (int) (e2.getX() - e1.getX());

                if ((Math.abs(dx) > MAJOR_MOVE) && (Math.abs(velocityX) > Math.abs(velocityY))) {
                    if (velocityX > 0) {
                        previousMsg();
                    } else {
                        nextMsg();
                    }

                    return true;
                } else {
                    return false;
                }
            }

        });

        mGestureDetector.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener() {

            @Override
            public boolean onSingleTapConfirmed(MotionEvent e) {
                return false;
            }

            @Override
            public boolean onDoubleTapEvent(MotionEvent e) {
                return false;
            }

            @Override
            public boolean onDoubleTap(MotionEvent e) {
                for (ConversationViewListener listener : mListeners) {
                    listener.onConversationViewDoubleTap(e);
                }

                return true;
            }
        });

        // Create 2 views for animations
        View.inflate(getContext(), R.layout.preview_msg, this);
        View.inflate(getContext(), R.layout.preview_msg, this);
    }

    public void previousMsg() {
        if (hasPreviousMessage()) {
            setOutAnimation(mAnimLeftOur);
            setInAnimation(mAnimLeftIn);

            ShortMessageView smv = getRecycledView();

            try {
                ShortMessage message;

                message = mConversation.getMessage(++mMessageVisibleIndex);
                updateView(smv, message);
                super.showNext();
                fireOnMessageVisibleChanged(mMessageVisibleIndex);
            } catch (IllegalAccessException e) {}
        }
    }

    public void nextMsg() {
        if (hasNextMessage()) {
            setOutAnimation(mAnimRightOut);
            setInAnimation(mAnimRightIn);

            ShortMessageView smv = getRecycledView();

            try {
                ShortMessage message;

                message = mConversation.getMessage(--mMessageVisibleIndex);
                updateView(smv, message);
                super.showNext();
                fireOnMessageVisibleChanged(mMessageVisibleIndex);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }

        }
    }

    private void updateView(final ShortMessageView view, final ShortMessage message) {

        if (mUiThread == Thread.currentThread()) {
            view.updateView(message, getContext());
        } else {
            getHandler().post(new Runnable() {
                @Override
                public void run() {
                    view.updateView(message, getContext());
                }
            });
        }
    }

    public void bind(Conversation conversation) {
        mConversation = conversation;
        mConversation.addListenerMessages(this);

        mMessageVisibleIndex = 0;

        if (mConversation.getMessageCount() > 0) {
            ShortMessage m;

            try {
                m = mConversation.getMessage(0);

                ShortMessageView v = (ShortMessageView) getChildAt(0);

                v.updateView(m, getContext());
            } catch (IllegalAccessException e3) {}
        }
    }

    public void unbind() {
        mConversation.removeListenerMessages(this);
    }

    public void addListener(ConversationViewListener l) {
        mListeners.add(l);
    }

    public void removeListener(ConversationViewListener l) {
        mListeners.remove(l);
    }

    public void fireOnMessageVisibleChanged(int index) {
        for (ConversationViewListener l : mListeners) {
            l.onMessageVisibleChanged(index);
        }
    }

    @Override
    public void onAddedMessages(int count, AddType type) {
        if (type == AddType.NEW_MESSAGE_ADDED_IN_HEAD) {
            mMessageVisibleIndex += count;
            fireOnMessageVisibleChanged(mMessageVisibleIndex);
        }
    }

    //~--- inner interfaces ---------------------------------------------------

    public interface ConversationViewListener {
        public void onConversationViewDoubleTap(MotionEvent e);

        public void onMessageVisibleChanged(int index);
    }
}
